import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        /**
         * 接收数据
         * */
        Scanner in = new Scanner(System.in);
        // -接收物品个数和背包体积
        int n = in.nextInt();
        int v = in.nextInt();
        // -接收背包内容
        int[][] bag = new int[n][2];
        for(int i = 0; i < n; i++) {
            bag[i][0] = in.nextInt();
            bag[i][1] = in.nextInt();
        }
        // -打印接收内容，查看是否接收正确
        // System.out.println("n:" + n);
        // System.out.println("v:" + v);
        // for(int i = 0; i < n; i++) {
        //      System.out.println(bag[i][0] + "|" + bag[i][1]);
        // }

        /**
         * 01背包问题解题逻辑
         *  第一问：求背包之多能装多大价值的物品
         *  状态表示：
         *      dp[i][j]表示装第i件物品时，总体积不超过j，此时的最大价值
         *  状态转移方程：
         *      dp[i][j] = dp[i-1][j];
         *      if(i <= j) {
         *          dp[i][j] = Math.max(dp[i][j], dp[i-1][j-bag[i][0]] + bag[i][1])
         *      }
         *  初始化：
         *      无需初始化
         *  返回值：
         *      返回dp[n][v];
         *  第二问：若背包恰好装满，求至多能装多大价值的物品
         *  状态表示：
         *      full[i][j]表示装第i件物品时，总体积等于j，此时的最大价值
         * */
        // 1 预处理

        // 2 创建dp表
        int[][] dp = new int[n+1][v+1];
        int[][] full = new int[n+1][v+1];
        // 3 初始化

        // 4 填表
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= v; j++) {
                dp[i][j] = dp[i-1][j];
                if(bag[i-1][0] <= j) {
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-bag[i-1][0]] + bag[i-1][1]);
                }
                full[i][j] = full[i-1][j];
                if(bag[i-1][0] == j || bag[i-1][0] <= j && full[i-1][j-bag[i-1][0]] != 0) {
                    full[i][j] = Math.max(full[i][j], full[i-1][j-bag[i-1][0]] + bag[i-1][1]);
                }
            }
        }
        // 5 返回值
        System.out.println(dp[n][v]);
        System.out.println(full[n][v]);
    }
}